package com.youlu.campus.service.english;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.entity.ActivityQaInfo;
import com.youlu.campus.entity.english.*;
import com.youlu.campus.entity.english.vo.request.QueryQaHomeCommand;
import com.youlu.campus.entity.english.vo.response.MyQaScoreResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserCompetitionQaService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserCompetitionFeeService userCompetitionFeeService;

    private final static String USER_QA_LIMIT = "campus:english:qa:limit:%s:%s";

    private final static String USER_QA_LIMIT_LOCK = "campus:english:qa:limit:lock:%s:%s";

    @Async
    public void updateUserInfo(UserCompetition updateUserCompetition){
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(updateUserCompetition.getUserId()));
        Update update = new Update();
        update.set("name",updateUserCompetition.getName());
        update.set("nickName",updateUserCompetition.getNickName());
        update.set("universityId",updateUserCompetition.getUniversityId());
        update.set("universityName",updateUserCompetition.getUniversityName());
        update.set("updatedTime",updateUserCompetition.getUpdatedTime());
        this.mongoTemplate.updateMulti(query,update,UserCompetitionQa.class);
        this.mongoTemplate.updateMulti(query,update,UserCompetitionQaCa.class);
    }


    public void doUniversity(){
        Query query = new Query();
        List<UserCompetition> userList = this.mongoTemplate.find(query, UserCompetition.class);
        userList.parallelStream().forEach(userCompetition -> {
            Query query1 = new Query();
            query1.addCriteria(Criteria.where("userId").is(userCompetition.getUserId()));
            Update update = new Update();
            update.set("universityId",userCompetition.getUniversityId());
            update.set("universityName",userCompetition.getUniversityName());
            this.mongoTemplate.updateMulti(query1,update,UserCompetitionQa.class);
        });


    }

    public Long qaCount(String currentUserId, String qaInfoId, Integer count) {
        String key = String.format(USER_QA_LIMIT, currentUserId, qaInfoId);
        Boolean hasKey = redisTemplate.hasKey(key);
        UserQaCountLog userQaCountLog = new UserQaCountLog();
        userQaCountLog.setUserId(currentUserId);
        userQaCountLog.setQaInfoId(qaInfoId);
        userQaCountLog.setCreatedTime(new Date());
        log.info("英语竞赛QA 用户 - >{} 答题 - > {}操作",currentUserId,qaInfoId);
        //如果不存在key。插入
        if (!hasKey) {
            ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
            Boolean existLockKey = redisTemplate.opsForValue().setIfAbsent(String.format(USER_QA_LIMIT_LOCK, currentUserId, qaInfoId), "1", 3L, TimeUnit.SECONDS);
            log.info("【英语竞赛-获取答题次数】获取锁状态->{}", existLockKey);
            if (Objects.nonNull(existLockKey)&&!existLockKey) {
               return (long)activityQaInfo.getTotalQaNum();
            }
            if (Objects.nonNull(activityQaInfo) && activityQaInfo.getTotalQaNum() >= 1) {
                userQaCountLog.setQaCount((long)activityQaInfo.getTotalQaNum());
                userQaCountLog.setRemark("初始化");
                this.mongoTemplate.save(userQaCountLog);
                log.info("英语竞赛QA 用户 - >{} 答题 - > {}操作 初始化 次数->{}",currentUserId,qaInfoId,userQaCountLog.getQaCount());
                return redisTemplate.opsForValue().increment(key, activityQaInfo.getTotalQaNum());
            }
        }
        //大于0 用于查询题库判断是否满足答题条件次数
        if (count > 0) {
            String incrValue = redisTemplate.opsForValue().get(key);
            log.info("英语竞赛QA 用户 - >{} 答题 - > {}操作 读取获取次数->{}",currentUserId,qaInfoId,incrValue);
            if(StringUtils.isBlank(incrValue)){
                return 0L;
            }
            userQaCountLog.setRemark("查询");
            userQaCountLog.setQaCount(Long.valueOf(incrValue));
            this.mongoTemplate.save(userQaCountLog);
            return Long.valueOf(incrValue);
        }
        //小于0答题相减
        if (count < 0) {
            Long subQaCount = redisTemplate.opsForValue().increment(key, count);
            userQaCountLog.setRemark("扣减次数");
            userQaCountLog.setQaCount(subQaCount);
            this.mongoTemplate.save(userQaCountLog);
            log.info("英语竞赛QA 用户 - >{} 答题 - > {}操作 扣减次数->{}",currentUserId,qaInfoId,userQaCountLog.getQaCount());
            return subQaCount;
        }
        return -1L;
    }

    public   List<MyQaScoreResponse> myScore(String userId){
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        List<UserCompetitionQa> list = this.mongoTemplate.find(query, UserCompetitionQa.class);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        List<MyQaScoreResponse> qaScoreList = new ArrayList<>();
        Map<String, List<UserCompetitionQa>> scoreMap = list.stream().collect(Collectors.groupingBy(userCompetitionQa -> userCompetitionQa.getActivityGroupId()));
        scoreMap.forEach((groupName,item)->{
            Optional<UserCompetitionQa> chuSaiOptional = item.stream().filter(userQa -> ActivityGroupQaType.QA_CHU_SAI.equals(userQa.getQaCode())).findAny();
            if(chuSaiOptional.isPresent()){
                UserCompetitionQa userCompetitionQa = chuSaiOptional.get();
                buildMyScore(qaScoreList,userCompetitionQa,"初赛");
            }
            Optional<UserCompetitionQa> fuSaiOptional = item.stream().filter(userQa -> ActivityGroupQaType.QA_FU_SAI.equals(userQa.getQaCode())).findAny();
            if(fuSaiOptional.isPresent()){
                UserCompetitionQa userCompetitionQa = fuSaiOptional.get();
                buildMyScore(qaScoreList,userCompetitionQa,"复赛");
            }
            Optional<UserCompetitionQa> juSaiOptional =
                    item.stream().filter(userQa -> ActivityGroupQaType.QA_JUE_SAI.equals(userQa.getQaCode())).findAny();
            if(juSaiOptional.isPresent()){
                UserCompetitionQa userCompetitionQa = juSaiOptional.get();
                buildMyScore(qaScoreList,userCompetitionQa,"决赛");
            }
        });
        return qaScoreList;
    }

    private void buildMyScore(List<MyQaScoreResponse> qaScoreList, UserCompetitionQa userQa, String qaAliasName){
        MyQaScoreResponse myQaScoreResponse = new MyQaScoreResponse();
        myQaScoreResponse.setActivityGroupName(userQa.getActivityGroupName());
        myQaScoreResponse.setQaAliasName(userQa.getActivityGroupName()+qaAliasName);
        if(CollectionUtils.isNotEmpty(userQa.getQaScoreLevelList())){
            ScoreMappingLevel scoreMappingLevel = userQa.getQaScoreLevelList().stream().max(Comparator.comparing(ScoreMappingLevel::getScore)).get();
            myQaScoreResponse.setScore(scoreMappingLevel.getScore());
        }
        qaScoreList.add(myQaScoreResponse);
    }

    public UserCompetitionQa findByUserIdAndScore(QueryQaHomeCommand queryQaHomeCommand) {
        String activityGroupId = queryQaHomeCommand.getActivityGroupId();
        String qaInfoId = queryQaHomeCommand.getQaInfoId();
        String userId = queryQaHomeCommand.getCurrentUser().getId();
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        ActivityGroup activityGroup = this.mongoTemplate.findById(activityGroupId, ActivityGroup.class);
        String caType = "";
        Optional<ActivityGroupQaType> activityGroupOptional = activityGroup.getQaTypeList().stream().filter(qaType -> qaInfoId.equals(qaType.getQaInfoId())).findAny();
        if (activityGroupOptional.isPresent()) {
            ActivityGroupQaType activityGroupQaType = activityGroupOptional.get();
            caType = activityGroupQaType.getAliasName();
        }
        UserCompetitionFee userCompetitionFee = userCompetitionFeeService.findActivityGroupIdAndQaInfoId(userId, activityGroupId, qaInfoId);
        Optional<ActivityGroupQaType> userCompetitionFeeOptional = userCompetitionFee.getBuyQaTypeList().stream().filter(buyQaInfo -> buyQaInfo.getQaInfoId().equals(qaInfoId) && Boolean.TRUE.equals(buyQaInfo.getLock())).findAny();
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("qaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
        UserCompetitionQa userCompetitionQa = this.mongoTemplate.findOne(query, UserCompetitionQa.class);
        if (Objects.isNull(userCompetitionQa) || CollectionUtils.isEmpty(userCompetitionQa.getQaScoreLevelList())) {
            userCompetitionQa = new UserCompetitionQa();
            userCompetitionQa.setQaLimit(qaCount(userId, qaInfoId, 1).intValue());
            userCompetitionQa.setScore(0D);
            userCompetitionQa.setQaDetail(activityQaInfo.getDetail());
            userCompetitionQa.setCaLevel("暂无等级");
            userCompetitionQa.setFeeTypeCode(userCompetitionFee.getFeeTypeCode());
            userCompetitionQa.setQaCode(userCompetitionFeeOptional.get().getCode());
            userCompetitionQa.setActivityGroupId(activityGroupId);
            userCompetitionQa.setCaType(caType);
            userCompetitionQa.setUniversityId(userCompetitionFee.getUniversityId());
            userCompetitionQa.setUniversityName(userCompetitionFee.getUniversityName());
            return userCompetitionQa;
        }
        ScoreMappingLevel scoreMappingLevel = userCompetitionQa.getQaScoreLevelList().stream().max(Comparator.comparing(ScoreMappingLevel::getScore)).get();
        userCompetitionQa.setScore(scoreMappingLevel.getScore());
        userCompetitionQa.setCaLevel(scoreMappingLevel.getLevel());
        userCompetitionQa.setQaLimit(qaCount(userId, qaInfoId, 1).intValue());
        userCompetitionQa.setQaDetail(activityQaInfo.getDetail());
        userCompetitionQa.setFeeTypeCode(userCompetitionFee.getFeeTypeCode());
        userCompetitionQa.setQaCode(userCompetitionFeeOptional.get().getCode());
        userCompetitionQa.setCaType(caType);
        userCompetitionQa.setReceiveCa(Boolean.TRUE);
        return userCompetitionQa;
    }
}
